package com.smedi.ismedi.database.starter.util;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * @Author: xulinjun
 * @Date: 2021-7-27 19:13
 */
@Slf4j
public class ReflectUtil {
    /**
     * 获取所有方法
     *
     * @param clazz
     * @return
     */
    private List<Method> getAllMethods(Class<? extends Object> clazz) {
        List<Method> methods = new ArrayList<>();
        while (clazz != null && !clazz.getName().equals(Object.class.getName())) {
            if (methods.size() <= 0) {
                methods.addAll(Arrays.asList(clazz.getMethods()));
            } else {
                Method[] array = clazz.getMethods();
                for (Method target : array) {
                    if (!methods.stream().filter(method -> method.getName().equals(target.getName())).findAny().isPresent()) {
                        methods.add(target);
                    }
                }
            }
            clazz = clazz.getSuperclass();
        }

        return methods;
    }

    /**
     * 调用方法
     *
     * @param classPath
     * @param methodName
     * @param <T>
     * @return
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws InvocationTargetException
     */
    public <T> T invoke(String classPath, String methodName) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Class<? extends Object> clazz = Class.forName(classPath);
        Object object = clazz.newInstance();

        List<Method> methods = getAllMethods(clazz);
        Optional<Method> optional = methods.stream().filter(method -> method.getName().equals(methodName)).findFirst();
        if (optional.isPresent()) {
            return (T) optional.get().invoke(object);
        } else {
            return null;
        }
    }
}
